		TITLE	COMMUNAL - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SYMBOLS
		INCLUDE	SEGMENTS
		INCLUDE	MODULES
		INCLUDE	EXES

		PUBLIC	DEFINE_COMMUNALS


		.DATA

		EXTERNDEF	SEG_COMBINE:BYTE,PUB_SIZE:BYTE,PUB_TYPE:BYTE,SEG32_FLAGS:BYTE,EXETYPE_FLAG:BYTE

		EXTERNDEF	PUB_CV:DWORD,CLASS_NAME_LINDEX:DWORD,CURNMOD_GINDEX:DWORD,FIRST_COMMUNAL_GINDEX:DWORD
		EXTERNDEF	PUB_SEGMOD_GINDEX:DWORD,PUB_GROUP_GINDEX:DWORD,FAR_BSS_SEGMOD_GINDEX:DWORD,SEG_NAME_LINDEX:DWORD
		EXTERNDEF	C_COMMON_SEGMOD_GINDEX:DWORD,MOD_FIRST_PUBLIC_GINDEX:DWORD,PUB_OFFSET:DWORD,SEG_LEN:DWORD
		EXTERNDEF	COMM_SIZE_A:DWORD,COMM_SIZE_B:DWORD

		EXTERNDEF	BSS_TPTR:TPTR_STRUCT,c_common_TPTR:TPTR_STRUCT,DGROUP_TPTR:TPTR_STRUCT,FAR_BSS_TPTR:TPTR_STRUCT
		EXTERNDEF	HUGE_BSS_TPTR:TPTR_STRUCT,SYMBOL_GARRAY:STD_PTR_S,MODULE_GARRAY:STD_PTR_S,SEGMOD_GARRAY:STD_PTR_S


		.CODE	MIDDLE_TEXT

		EXTERNDEF	GET_32:PROC,DEFINE_SEGMOD:PROC,FIX_COMMUNAL_ENTRY:PROC,GET_GROUP:PROC
		EXTERNDEF	PUT_SM_IN_GROUP:PROC,MAKE_TPTR_LINDEX:PROC,PUT_EAX_IN_DGROUP:PROC,INIT_LOCAL_STORAGE:PROC
		EXTERNDEF	RELEASE_LOCAL_STORAGE:PROC,WARN_RET:PROC

		EXTERNDEF	COMMUNAL_ERR:ABS


DEFINE_COMMUNALS	PROC
		;
		;
		;
		XOR	EAX,EAX

		MOV	PUB_SIZE,AL
		MOV	PUB_GROUP_GINDEX,EAX

		MOV	PUB_CV,EAX
		MOV	AL,MASK SEG32_USE16
if	fg_pe OR fg_dosx
		BITT	OUTPUT_32BITS
		JZ	L0$
		MOV	AL,MASK SEG32_USE32
L0$:
endif
		MOV	SEG32_FLAGS,AL			;NEITHER USE16 NOR USE32

		MOV	PUB_TYPE,NSYM_RELOC

		CALL	INIT_LOCAL_STORAGE
		;
		;FIRST DO EVEN SIZED ITEMS
		;
		MOV	ESI,FIRST_COMMUNAL_GINDEX
		JMP	L14$

		;
		;FIRST DO THINGS THAT ARE MULTIPLES OF DWORDS IN SIZE...
		;
L1$:
		MOV	EBX,ESI
		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT
		MOV	AL,BPTR [ESI]._COMM_SIZE_A	;ELSE CHECK FOR ODD

		MUL	BPTR [ESI]._COMM_SIZE_B		;ELEMENT SIZE

		TEST	AL,3
		MOV	ECX,ESI

		MOV	ESI,[ESI]._COMM_NEXT_SYM_GINDEX
		JNZ	L14$
L12$:
		MOV	EAX,EBX
		CALL	PROC_COMMUNAL
L14$:
		TEST	ESI,ESI
		JNZ	L1$

		MOV	ESI,FIRST_COMMUNAL_GINDEX
		JMP	L25$

		;
		;NEXT DO ANY THAT ARE MULTIPLE OF WORDS IN SIZE
		;
L2$:
		MOV	EBX,ESI
		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT
		MOV	AL,BPTR [ESI]._COMM_SIZE_A	;ELSE CHECK FOR ODD

		MOV	DL,BPTR [ESI]._COMM_SIZE_B	;ELEMENT SIZE
		MOV	ECX,ESI

		AND	AL,DL
		MOV	ESI,[ESI]._COMM_NEXT_SYM_GINDEX

		TEST	AL,1
		JNZ	L25$

		MOV	EAX,EBX
		CALL	PROC_COMMUNAL
L25$:
		TEST	ESI,ESI
		JNZ	L2$

		MOV	ESI,FIRST_COMMUNAL_GINDEX
		JMP	L9$

		;
		;NEXT DO ALL THE ODD LEFT-OVERS
		;
L6$:
		MOV	EAX,ESI
		CONVERT	ESI,ESI,SYMBOL_GARRAY
		ASSUME	ESI:PTR SYMBOL_STRUCT
		MOV	ECX,ESI

		MOV	ESI,[ESI]._COMM_NEXT_SYM_GINDEX
		CALL	PROC_COMMUNAL
L9$:
		TEST	ESI,ESI
		JNZ	L6$

		MOV	CURNMOD_GINDEX,ESI
		JMP	RELEASE_LOCAL_STORAGE

DEFINE_COMMUNALS	ENDP


PROC_COMMUNAL	PROC	NEAR
		;
		;ECX (EAX) IS SYMBOL
		;
		PUSH	ESI
		MOV	ESI,ECX

		PUSH	EBX
		MOV	EBX,EAX

		MOV	AL,[ESI]._COMM_NSYM_TYPE
		MOV	ECX,[ESI]._COMM_MOD_GINDEX

		CMP	AL,NSYM_COMM_NEAR	;NEAR?
		JNZ	DO_COMM_FAR
;		JMP	DO_COMM_NEAR

PROC_COMMUNAL	ENDP


DO_COMM_NEAR	PROC	NEAR
		;
		;ESI IS PHYS, EBX IS GINDEX
		;
		;THIS IS A 'NEAR' COMMUNAL.  HAS THE SEGMENT BEEN DEFINED?
		;
		MOV	EDX,C_COMMON_SEGMOD_GINDEX
		MOV	CURNMOD_GINDEX,ECX

		TEST	EDX,EDX
		JZ	GET_C_COMMON
GET_C_RET:
		;
		;CALC TOTAL SIZE OF THIS VARIABLE
		;
		MOV	EAX,[ESI]._COMM_SIZE_A
		MOV	PUB_GROUP_GINDEX,EDX		;NON-ZERO FLAG

		MUL	[ESI]._COMM_SIZE_B

		PUSH	EAX
		MOV	EDX,C_COMMON_SEGMOD_GINDEX	;EDX IS SEGMOD_GINDEX

		MOV	EAX,EBX
		MOV	ECX,ESI

		CALL	DO_FIX_COMMUNAL			;ECX IS PHYS, EAX IS GINDEX

		MOV	EAX,C_COMMON_SEGMOD_GINDEX
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT
		POP	ECX

		POPM	EBX,ESI

		ADD	[EAX]._SM_LEN,ECX

		RET

GET_C_COMMON:
		CALL	GET_C_COMMON_RTN

		MOV	EDX,C_COMMON_SEGMOD_GINDEX
		JMP	GET_C_RET

DO_COMM_NEAR	ENDP


DO_COMM_FAR	PROC	NEAR
		;
		;ESI IS PHYS, EBX IS LOG
		;
		;THIS IS A 'FAR' OR 'HUGE' COMMUNAL.  WHICH IS IT ?
		;CALC SIZE OF THIS VARIABLE
		;
		XOR	EDX,EDX
		MOV	CURNMOD_GINDEX,ECX

		MOV	EAX,[ESI]._COMM_SIZE_A
		MOV	PUB_GROUP_GINDEX,EDX

		MUL	[ESI]._COMM_SIZE_B

if	fg_pe OR fg_dosx
		MOV	DL,SEG32_FLAGS

		AND	DL,MASK SEG32_USE32
		JNZ	L1$
endif
		CMP	EAX,64K
		JA	DO_COMM_HUGE1
L1$:
		PUSH	EAX
		;
		;THIS IS A 'FAR' COMMUNAL.  DOES SEGMENT EXIST?
		;
		MOV	EDI,FAR_BSS_SEGMOD_GINDEX

		PUSH	ECX
		TEST	EDI,EDI

		MOV	ECX,EAX
		JZ	GET_ANOTHER_FAR_BSS

		MOV	EDX,EDI
		;
		;IS THERE ROOM FOR THIS VARIABLE, OR GO GET ANOTHER?
		;
		MOV	AL,SEG32_FLAGS

		AND	AL,MASK SEG32_USE32
		JNZ	DCF_1

		CONVERT	EDI,EDI,SEGMOD_GARRAY
		ASSUME	EDI:PTR SEGMOD_STRUCT

		MOV	EAX,[EDI]._SM_LEN

		CMP	EAX,64K
		JAE	GET_ANOTHER_FAR_BSS		;ALREADY 64K, GET ANOTHER

		ADD	EAX,ECX

		CMP	EAX,64K
		JA	GET_ANOTHER_FAR_BSS		;I'M PUSHING IT PAST 64K
DCF_1:
		POP	ECX
GAFB_RET:
		MOV	EAX,EBX
		MOV	ECX,ESI

		CALL	DO_FIX_COMMUNAL		;DS:SI IS PHYS, CX IS GINDEX,
						;DX IS SEGMOD GINDEX
		MOV	EAX,FAR_BSS_SEGMOD_GINDEX
		POP	ECX

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		POPM	EBX,ESI

		ADD	[EAX]._SM_LEN,ECX

		RET


GET_ANOTHER_FAR_BSS:
		;
		;SET UP FAR_BSS SEGMENT...
		;
		MOV	EAX,OFF FAR_BSS_TPTR
		CALL	MAKE_TPTR_LINDEX

		MOV	CLASS_NAME_LINDEX,EAX
		MOV	SEG_NAME_LINDEX,EAX
		;
		MOV	WPTR SEG_COMBINE,300H	;PARA PRIVATE

		PUSH	ESI
		CALL	DEFINE_SEGMOD_M0	;AX IS SEGMOD, DS:BX IS PHYS

		POPM	ESI,ECX

		MOV	FAR_BSS_SEGMOD_GINDEX,EAX
		MOV	EDX,EAX

		JMP	GAFB_RET


DO_COMM_HUGE1:
		MOV	EBX,[ESI]._COMM_SIZE_A
		MOV	EDX,[ESI]._COMM_SIZE_B

		MOV	COMM_SIZE_A,EBX
		MOV	COMM_SIZE_B,EDX

		PUSH	ECX		;SAVE SYMBOL GINDEX
		;
		;THIS IS A 'HUGE' COMMUNAL.  DOES SEGMENT EXIST?
		;
		PUSH	EAX		;SAVE SIZE
		CALL	GET_ANOTHER_HUGE_BSS	;EAX IS SEGMOD GINDEX

		MOV	EBX,EAX
		XOR	ECX,ECX

		POP	EAX
		PUSH	ECX		;OFFSET TO FIRST ELEMENT

		PUSH	EBX		;SAVE FIRST HUGE_BSS
		PUSH	EAX		;COMMUNAL SIZE...
		;
		;CALCULATE OFFSET NEEDED BECAUSE OF NON-POWER OF 2
		;
		MOV	ECX,COMM_SIZE_B
		MOV	EAX,64K

		TEST	CX,CX
		JZ	KEEP_0		;OBJECT IS A POWER OF 64K... KEEP 0 OFFSET

		CMP	ECX,EAX
		JA	WARN_H		;ONE ELEMENT >64K ERROR?

		CMP	ECX,3
		JC	KEEP_0		;1 OR 2 BYTE ELEMENTS

		XOR	EDX,EDX

		DIV	ECX

		TEST	EDX,EDX
		JZ	KEEP_0		;FITS EVENLY IN 64K
		;
		;EDX IS OFFSET FROM 0 TO FIRST ELEMENT OF ARRAY
		;EAX IS # OF ELEMENTS THAT FIT IN 64K
		;
		MOV	ECX,COMM_SIZE_A
		ADD	EAX,EAX


		CMP	ECX,EAX			;HUGE ERROR IF MORE THAN 2 64K SEGMENTS TOTAL
		JA	WARN_H
		;
		;OK, SAVE OFFSET TO FIRST ELEMENT
		;
		MOV	EAX,EDX
		POPM	ECX,EBX,ESI		;THROW AWAY OFFSET TO FIRST

		ADD	ECX,EAX			;ADD THAT TO TOTAL TO BE ALLOCATED
		PUSHM	EAX,EBX,ECX
KEEP_0:
		MOV	EDX,EBX			;MOVE SEGMOD_GINDEX
		JMP	DEFAULT

WARN_H:
		MOV	AL,COMMUNAL_ERR
		CALL	WARN_RET
		JMP	KEEP_0

DEF_1:
		PUSH	EAX
		CALL	GET_ANOTHER_HUGE_BSS

		MOV	EDX,EAX
DEFAULT:
		CONVERT	EDX,EDX,SEGMOD_GARRAY
		ASSUME	EDX:PTR SEGMOD_STRUCT

		MOV	ECX,64K
		POP	EAX

		MOV	[EDX]._SM_LEN,ECX	;MARK IT 64K IN SIZE

		SUB	EAX,ECX
		JA	DEF_1			;JUMP IF MORE 64K SEGS NEEDED

		ADD	EAX,ECX
		JZ	DO_HUGE_SYMBOL

		PUSH	EAX
		CALL	GET_ANOTHER_HUGE_BSS	;DO PARTIAL SEGMENT...
		ASSUME	ECX:PTR SEGMOD_STRUCT

		POP	EAX

		MOV	[ECX]._SM_LEN,EAX
DO_HUGE_SYMBOL:
		POP	EAX			;ORIGINAL SEGMOD
		POP	EDI			;OFFSET TO FIRST ELEMENT
		POP	ECX			;SYMBOL LOGICAL
		MOV	EDX,EAX

		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	EBX,[EAX]._SM_LEN
		MOV	[EAX]._SM_LEN,EDI

		PUSHM	EBX,EDX

		CALL	DO_FIX_COMMUNAL		;DS:SI IS SYMBOL PHYS, CX IS GINDEX,
						;DX IS SEGMOD GINDEX
		POPM	EAX,EBX
		CONVERT	EAX,EAX,SEGMOD_GARRAY
		ASSUME	EAX:PTR SEGMOD_STRUCT

		MOV	[EAX]._SM_LEN,EBX

		RET


DO_COMM_FAR	ENDP


GET_ANOTHER_HUGE_BSS	PROC
		;
		;RETURNS DX AS SEGMOD GINDEX
		;
		;SET UP HUGE_BSS SEGMENT...
		;
		MOV	EAX,OFF HUGE_BSS_TPTR
		CALL	MAKE_TPTR_LINDEX

		MOV	WPTR SEG_COMBINE,300H	;PARA PRIVATE

		MOV	CLASS_NAME_LINDEX,EAX
		MOV	SEG_NAME_LINDEX,EAX
		;
		JMP	DEFINE_SEGMOD_M0	;EAX IS SEGMOD, ECX IS PHYS

GET_ANOTHER_HUGE_BSS	ENDP


GET_C_COMMON_RTN	PROC	NEAR
		;
		;SET UP c_common SEGMENT...
		;
		MOV	EAX,OFF BSS_TPTR
		CALL	MAKE_TPTR_LINDEX

		MOV	CLASS_NAME_LINDEX,EAX
		MOV	EAX,OFF c_common_TPTR

		CALL	MAKE_TPTR_LINDEX

		MOV	WPTR SEG_COMBINE,302H	;PARA PUBLIC

		MOV	SEG_NAME_LINDEX,EAX
		CALL	DEFINE_SEGMOD_M0	;AX IS SEGMOD_GINDEX, DS:BX IS PHYS

		MOV	C_COMMON_SEGMOD_GINDEX,EAX
		;
		;NOW STICK THIS THING IN DGROUP...
		;
		JMP	PUT_EAX_IN_DGROUP	;HANDLES CREATING DGROUP...

GET_C_COMMON_RTN	ENDP


DO_FIX_COMMUNAL	PROC	NEAR
		;
		;ECX IS PHYSICAL, EAX IS GINDEX, EDX IS SEGMOD GINDEX
		;
		PUSH	ESI
		MOV	ESI,CURNMOD_GINDEX

		CONVERT	ESI,ESI,MODULE_GARRAY
		ASSUME	ESI:PTR MODULE_STRUCT

		MOV	PUB_SEGMOD_GINDEX,EDX
		CONVERT	EDX,EDX,SEGMOD_GARRAY
		ASSUME	EDX:PTR SEGMOD_STRUCT
		MOV	EDX,[EDX]._SM_LEN

		MOV	PUB_OFFSET,EDX
		MOV	EDX,[ESI]._M_FIRST_PUB_GINDEX

		MOV	MOD_FIRST_PUBLIC_GINDEX,EDX
		CALL	FIX_COMMUNAL_ENTRY	;ECX IS PHYSICAL, EAX IS GINDEX

		MOV	ECX,MOD_FIRST_PUBLIC_GINDEX

		MOV	[ESI]._M_FIRST_PUB_GINDEX,ECX
		POP	ESI

		RET

DO_FIX_COMMUNAL	ENDP


DEFINE_SEGMOD_M0	PROC	NEAR
		;
		;FAKE A NON-ZERO LENGTH SEGMENT....
		;
		MOV	EAX,10

		MOV	SEG_LEN,EAX
		CALL	DEFINE_SEGMOD
		ASSUME	ECX:PTR SEGMOD_STRUCT

		XOR	EDX,EDX

		MOV	[ECX]._SM_LEN,EDX

		RET

DEFINE_SEGMOD_M0	ENDP


		END

